package cz.vse.javaee.album;

import javax.annotation.PostConstruct;
import javax.ejb.LocalBean;
import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

@Stateful
@LocalBean
public class PhotoPaginator implements Iterator<List<PhotoWithAlbumBasicTO>> {

    @PersistenceContext(unitName = "album")
    private EntityManager entityManager;
    private EntityFragmentManager entityFragmentManager;

    private int pageSize = 3;
    private int index = -1;
    private boolean next = true;
    private String albumName;

    @PostConstruct
    public void init() {
        entityFragmentManager = new EntityFragmentManager(entityManager);

        Query q = entityManager.createQuery("select a from Album a order by a.name");
        q.setMaxResults(1);
        List<Album> albums = q.getResultList();
        if (!albums.isEmpty()) {
            albumName = albums.get(0).getName();
        }
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
        index = -1;
        next = true;
    }

    public int getPageSize() {
        return pageSize;
    }

    private int getFirst() {
        return index * pageSize;
    }

    public boolean hasNext() {
        return next;
    }

    public int getIndex() {
        return index;
    }

    public List<PhotoWithAlbumBasicTO> first() {
        index = 0;
        return fetchPage();
    }

    public List<PhotoWithAlbumBasicTO> last() {
        long total = getSize();
        long lastIndex = total == 0 ? 0 : (total - 1) / pageSize;
        index = (int) lastIndex;
        return fetchPage();
    }

    public List<PhotoWithAlbumBasicTO> next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        index++;
        return fetchPage();
    }

    public boolean hasPrevious() {
        return index > 0;
    }

    public List<PhotoWithAlbumBasicTO> previous() {
        if (!hasPrevious()) {
            throw new NoSuchElementException();
        }
        index--;
        return fetchPage();
    }

    private List<PhotoWithAlbumBasicTO> fetchPage() {
        if (albumName == null) {
            return Collections.emptyList();
        }

        EntityFragmentManager.FragmentQuery<PhotoWithAlbumBasicTO> q =
                entityFragmentManager.createQuery(PhotoWithAlbumBasicTO.class, "p.album.name=:albumName");
        q.setParameter("albumName", albumName);
        q.setFirstResult(getFirst());
        q.setMaxResults(pageSize + 1);
        EntityFragmentManager.FragmentList<PhotoWithAlbumBasicTO> resultList = q.getResults();

//        Query q = entityManager.createQuery("select p from PhotoWithAlbumBasicTO p where p.album.name=:albumName");
//        q.setParameter("albumName", albumName);
//        q.setFirstResult(getFirst());
//        q.setMaxResults(pageSize + 1);
//        List resultList = q.getResultList();

//        for (PhotoWithAlbumBasicTO p : resultList) {
//            p.setPhotoDescription(p.getPhotoDescription() + "*");
//            try {
//                PhotoWithAlbumBasicTO p2 = entityFragmentManager.findFragment(PhotoWithAlbumBasicTO.class, p.getPhotoId());
//                entityFragmentManager.updateFragment(p);
//            } catch (Exception e) {
//                throw new RuntimeException(e);
//            }
//        }

        if (resultList.size() < pageSize + 1) {
            next = false;
            return resultList;
        } else {
            next = true;
            return (List<PhotoWithAlbumBasicTO>) resultList.subList(0, pageSize);
        }
    }

    public long getSize() {
        Query q = entityManager.createQuery("select count(p) from Photo p where p.album.name=:albumName");
        q.setParameter("albumName", albumName);
        return (Long) q.getSingleResult();
    }

    public void remove() {
        throw new UnsupportedOperationException();
    }

    @Remove
    public void close() {
        entityManager.clear();
        entityManager.close();
    }

    public List<PhotoWithAlbumBasicTO> setAlbumName(String albumName) {
        this.albumName = albumName;
        return first();
    }

    public String getAlbumName() {
        return albumName;
    }
}
    